package logica;

import java.rmi.RemoteException;

import org.apache.axis2.AxisFault;
import logica.ServicioLoginStub;
import logica.ServicioLoginStub.ValidateUser;
import logica.ServicioLoginStub.ValidateUserResponse;

import exceptions.ConexionException;
import exceptions.LogicaException;
import exceptions.PersistenciaException;

import persistencia.Configuracion;
import persistencia.Persistencia;

public class Fachada 
{
	private static Fachada instancia = null;
	private Emisor socketDifusion = null;
	private Receptor socketEquiposActivos = null;
	private Emisor socketEnvioMensajes = null;
	private Receptor socketRecepcionMensajes = null;
	private ServicioLoginStub clienteWs;
	
	private Fachada () throws PersistenciaException, LogicaException, ConexionException, AxisFault
	{
		/*
		 * 1. creo socketDifusion en el puerto 5001 para difundir que estoy activo
		 * 2. creo socketEquiposActivos en el puerto 5002 para recibir avisos de equipos activos
		 * 3. creo socketEnvioMensajes en el puerto 5003 para enviar mensaje personal a un equipo seleccionado
		 * 4. creo socketRecepcionMensajes en el puerto 5004 para recibir mensajes personales
	 	 */
		try {
			socketDifusion = new Emisor(Integer.parseInt(Configuracion.getInstancia().getProperty(Configuracion.PUERTO_DIFUSION)));
			socketEquiposActivos = new Receptor(Integer.parseInt(Configuracion.getInstancia().getProperty(Configuracion.PUERTO_EQUIPOS_ACTIVOS)));
			socketEnvioMensajes = new Emisor(Integer.parseInt(Configuracion.getInstancia().getProperty(Configuracion.PUERTO_ENVIO_MENSAJE)));
			socketRecepcionMensajes = new Receptor(Integer.parseInt(Configuracion.getInstancia().getProperty(Configuracion.PUERTO_RECEPCION_MENSAJE)));
			clienteWs = new ServicioLoginStub(Configuracion.getInstancia().getProperty(Configuracion.URL_SERVIDOR));
		} catch (NumberFormatException e) {
			throw new LogicaException(LogicaException.ERROR_CONEXION);
		}
	}
	
	public synchronized static Fachada getInstancia () throws PersistenciaException, LogicaException, ConexionException, AxisFault
	{
		if (instancia == null)
			instancia = new Fachada();
		return instancia;
	}
	
	public void difundirEstoyActivo () throws LogicaException, PersistenciaException
	{
		/* 
		 * Procedo a enviar un mensaje en broadcast difundiendo que estoy activo
		 * 1. Creo un paquete UDP conteni// TODO Auto-generated catch block
			endo el mensaje "ArqSoft" de 64 bytes
		 * 2. Lo difundo a toda la red por el socketDifusion a través de la IP de broadcast 255.255.255.255
		 */
		System.out.println("Fachada::difundirEstoyActivo");
		int puerto;
		try {
			puerto = Integer.parseInt(Configuracion.getInstancia().getProperty(Configuracion.PUERTO_EQUIPOS_ACTIVOS));
			socketDifusion.enviarMensaje("ArqSoft", "255.255.255.255", puerto);
		} catch (NumberFormatException e) {
			throw new LogicaException(LogicaException.ERROR_DIFUNDIR);
		}
	}
	
	public String recibirEquipoActivo ()
	{
		String ipEmisor = null;
		/*
		 * Procedo a recibir un mensaje de algún otro equipo que difundió que está activo
		 * 1. Recibo un paquete UDP de 64 bytes a través del socketEquiposActivos
		 * 2. Si trae el mensaje "ArqSoft", retorno un String con la dirección IP del emisor
		 * 3. Si no trae el mensaje "ArqSoft", retorno el String "ninguna"
		 */	
		System.out.println("Fachada::recibirEquipoActivo");
		
		ipEmisor = socketEquiposActivos.recibirMensaje();
		
		if (ipEmisor.equals("ArqSoft")) {
			ipEmisor = socketEquiposActivos.getUltimaIP();
			
			//Detecto si el emisor del mensaje soy yo
			if(ipEmisor.equals(socketDifusion.getIpEmisor())){
				ipEmisor = "ninguna";
			}else{
				System.out.println("Equipo activo: " + ipEmisor);
			}
		} else {
			ipEmisor = "ninguna";
		}
		return ipEmisor;
	}

	public void enviarMensaje (String mensaje, String ipEquipoSeleccionado) throws LogicaException, PersistenciaException
	{
		/* 
		 * Procedo a enviar el mensaje a la direccion IP del equipo seleccionado
		 * 1. Creo un paquete UDP de 64 bytes conteniendo el mensaje pasado por par�metro
		 * 2. Lo env�o a la IP del equipo seleccionado a través del socketEnvioMensajes
		 */
		System.out.println("Fachada::enviarMensaje");
		int puerto;
		try {
			puerto = Integer.parseInt(Configuracion.getInstancia().getProperty(Configuracion.PUERTO_RECEPCION_MENSAJE));
			if (!this.socketEnvioMensajes.enviarMensaje(mensaje, ipEquipoSeleccionado, puerto)) {
				throw new LogicaException(LogicaException.ERROR_ENVIAR_MENSAJE);
			}
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			throw new LogicaException(LogicaException.ERROR_ENVIAR_MENSAJE);
		}
	}

	public String recibirMensaje () throws PersistenciaException
	{
		String mensaje = null;
		String ultimaIp = null;
		/*
		 * Procedo a recibir un mensaje de algún otro equipo dirigido expresamente a mí
		 * 1. Recibo un paquete UDP de 64 bytes a través del socketRecepcionMensajes
		 * 2. Extraigo la IP del emisor + el contenido del mensaje y los retorno en un String
		 * 3. Agrego la IP del emisor + el contenido del mensaje al historial de mensajes en la Persistencia
		 */	
		System.out.println("Fachada::recibirMensaje");
		mensaje = socketRecepcionMensajes.recibirMensaje();
		ultimaIp = socketRecepcionMensajes.getUltimaIP();
		Persistencia.getInstancia().persistirMensaje(ultimaIp, mensaje);
		return "De    :" + ultimaIp + ": " + mensaje;
	}
	
	public String getLocalIP() {
		return socketRecepcionMensajes.getSocket().getLocalAddress().getHostAddress().toString();
	}
	
	public Boolean validateUser(String _name, String _psw) {
		boolean ret = false;
		try {	
			ValidateUser req = new ValidateUser();
			req.setName(_name);
			req.setPwd(_psw);
			ValidateUserResponse resp = this.clienteWs.validateUser(req);
			ret = resp.get_return();
		} catch (RemoteException e) {
			//throw new LogicaException(LogicaException.ERROR_COMUNICACION);
		}
		return ret;
	}
}
